package cn.gogoyc.user.service.impl;

import cn.gogoyc.org.basic.dto.EmailCodeDto;
import cn.gogoyc.org.basic.exception.BusinessException;
import cn.gogoyc.org.basic.servie.impl.BaseServiceImpl;
import cn.gogoyc.org.basic.util.Md5Utils;
import cn.gogoyc.org.basic.util.StrUtils;
import cn.gogoyc.user.domain.Logininfo;
import cn.gogoyc.user.domain.User;
import cn.gogoyc.user.mapper.LogininfoMapper;
import cn.gogoyc.user.mapper.UserMapper;
import cn.gogoyc.user.service.IUserService;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.util.Map;

/**
 * 用户业务实现类
 */
@Service
public class UserServiceImpl extends BaseServiceImpl<User> implements IUserService {
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private LogininfoMapper logininfoMapper;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private JavaMailSender javaMailSender;

    @Override
    public void registerPhone(Map<String, String> map) {
        //提取Map里面的值
        String phone = map.get("phone");
        String pwd = map.get("pwd");
        String rePwd = map.get("rePwd");
        String phoneCode = map.get("phoneCode");

        //空值判断如果有一个为null都弹窗提醒
        if (StringUtils.isEmpty(phone) || StringUtils.isEmpty(pwd) ||
            StringUtils.isEmpty(rePwd) || StringUtils.isEmpty(phoneCode)){
            throw new BusinessException("请认真填写数据哦!");
        }

        //两个密码是否一致,不一致则弹窗提醒
        if (!pwd.equals(rePwd)){
            throw new BusinessException("密码不一致!");
        }

        //获取redis里手机key-value
        Object o = redisTemplate.opsForValue().get("register:" + phone);
        //如果为null则验证码过期了,弹窗提醒前端
        if (o==null){
            throw new BusinessException("验证码已过期,请重新获取!");
        }

        //走到这里说明有验证码,因为redis里他是业务键拼接了的,所以要截取获取验证码
        String redisPhoneCode = o.toString().split(":")[0];

        //如果页面输入的验证码和redis里的验证码不一致则弹窗提醒
        if (!phoneCode.equals(redisPhoneCode)){
            throw new BusinessException("验证码不一致,请认真填写!");
        }

        //将一个对象转为另一个对象 使用格式obj2Obj格式
        //这里的User是根据map提供的数据进行添加属性了的
        User user = map2User(map);

        //再将User对象转为logininfo里面去用工具类复制属性
        Logininfo logininfo = user2Logininfo(user);

        //将复制好的对象添加到对应数据库中
        logininfoMapper.save(logininfo);

        //关联ID,获取logininfo的Id设置到User的logininfoId上,从而关联上
        user.setLogininfoId(logininfo.getId());
        //都设置好和关联好后添加到对应数据库中
        userMapper.save(user);

    }

    private Logininfo user2Logininfo(User user) {
        //创建loginginfo对象
        Logininfo logininfo = new Logininfo();
        //使用工具类,将User对象和logininfo对象的相同属性,赋值给logininfo对象
        BeanUtils.copyProperties(user,logininfo);

        //1=用户 0=员工
        //因为logininfo是一个公共表,里面有用户和员工,这里是添加用户,则把状态写死1
        logininfo.setType(1);
        //状态 ture=开启
        logininfo.setDisable(true);
        //都设置好属性后返回给调用方
        return logininfo;
    }

    private User map2User(Map<String, String> map) {
        User user = new User();
        //获取map中的phone属性 拎出来赋值
        String phone = map.get("phone");
        //电话和用户名都是手机号码
        user.setUsername(phone);
        user.setPhone(phone);
        //加盐加密
        String salt = StrUtils.getComplexRandomString(32);
        String md5Pwd = Md5Utils.encrypByMd5(salt);
        //将加盐加密好的密码设置进对象
        user.setPassword(md5Pwd);
        //将盐值添加进对象
        user.setSalt(salt);
        //默认启用
        user.setState(1);
        ////都设置好属性后返回给调用方
        return user;
    }


    @Override
    public void auditEmail(EmailCodeDto emailCodeDto) throws MessagingException {
        String email = emailCodeDto.getEmail();
        String pwd = emailCodeDto.getPwd();
        String rePwd = emailCodeDto.getRePwd();

        //根据邮箱查询是否有注册过
        User user = userMapper.loadByEmail(email);

        //!=null则是注册过 弹窗提醒
        if (user!=null){
            throw new BusinessException("该用户已注册,请直接登录");
        }
        //非空判断
        if (StringUtils.isEmpty(email) || StringUtils.isEmpty(pwd) || StringUtils.isEmpty(rePwd)){
            throw new BusinessException("请正确填写信息!");
        }
        //两次密码是否一致
        if (!pwd.equals(rePwd)){
            throw new BusinessException("密码不一致,请正确填写!");
        }

        MimeMessage mimeMessage = javaMailSender.createMimeMessage();
        //true - 能够添加附件
        MimeMessageHelper helper = new MimeMessageHelper(mimeMessage, true, "utf-8");
        helper.setFrom("1462058295@qq.com");
        helper.setSubject("宠物之家邮箱注册激活");
        //true - 能够再内容中编写html标签 - 会解析
        //rustful风格拼接
        helper.setText("<h3>请点击该链接进行邮箱注册激活，请<a href='http://127.0.0.1:8080/user/active/"+email
                +"/"+pwd+"'>点击这里</a>邮箱注册,点击后跳往登录界面进行登录!</h3>", true);
        //根据传入的邮箱发送注册邮件
        helper.setTo(email);
        //发送
        javaMailSender.send(mimeMessage);
    }

    @Override
    public void activatedEmail(String email, String pwd) {
        //加盐加密
        String salt = StrUtils.getComplexRandomString(32);
        String pwdSalt = salt+pwd;
        String md5Pwd = Md5Utils.encrypByMd5(pwdSalt);

        //对象设置值
        User user = new User();
        user.setEmail(email);
        user.setUsername(email);
        user.setState(1);
        user.setPassword(md5Pwd);
        user.setSalt(pwdSalt);

        //将设置好的对象用BeanUtil复制给logininfo对象
        Logininfo logininfo = user2Logininfo(user);
        //将复制好的对象添加到对应数据库中
        logininfoMapper.save(logininfo);

        //关联ID,获取logininfo的Id设置到User的logininfoId上,从而关联上
        user.setLogininfoId(logininfo.getId());
        //都设置好和关联好后添加到对应数据库中
        userMapper.save(user);
    }

    @Override
    public void save(User user) {
        String salt = StrUtils.getComplexRandomString(32);
        String md5Pwd = Md5Utils.encrypByMd5(user.getPassword() + salt);
        user.setSalt(salt);
        user.setPassword(md5Pwd);

        Logininfo logininfo = new Logininfo();
        BeanUtils.copyProperties(user,logininfo);
        logininfo.setType(1);
        logininfo.setDisable(true);
        logininfoMapper.save(logininfo);

        user.setLogininfoId(logininfo.getId());
        super.save(user);
    }

    @Override
    public void remove(Long id) {
        User user = userMapper.loadById(id);
        super.remove(id);
        logininfoMapper.remove(user.getLogininfoId());
    }

    @Override
    public void update(User user) {
        String salt = StrUtils.getComplexRandomString(32);
        String md5Pwd = Md5Utils.encrypByMd5(user.getPassword() + salt);
        user.setSalt(salt);
        user.setPassword(md5Pwd);

        User oldUser = userMapper.loadById(user.getId());

        user.setLogininfoId(oldUser.getLogininfoId());
        super.update(user);

        Logininfo oldLogininfo = logininfoMapper.loadById(oldUser.getLogininfoId());
        BeanUtils.copyProperties(user, oldLogininfo);
        oldLogininfo.setId(oldUser.getLogininfoId());
        logininfoMapper.save(oldLogininfo);
    }
}
